package com.smart.common.idem.handler;

import com.smart.common.idem.annation.ApiIdempotent;
import com.smart.common.idem.exception.ApiIdempotentException;
import com.smart.common.redis.dao.RedisDao;
import com.smart.common.vo.ResponseEnumCode;
import io.netty.util.internal.StringUtil;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//  什么是幂等性   执行n次跟执行一次的结果都是一样

/**
 * 不是所有的接口需要幂等性判断
 * 控制层使用定义一个注解
 * 在拦截中
 * 1. 获取注解对象
 * 如果注解对象为null  说明接口不需要做幂等性 直接返回true
 * 如果对象不为null  表示需要幂等性判断
 */

/**
 * 拦截器
 * 自定义注解
 * redis使用
 */
public class ApiIdempotentInterceptor extends HandlerInterceptorAdapter {
    public static final String API_IDEMPOTENT_TOKEN = "token";
    public static final String DEFAULT_API_IDEMPOTENT_TOKEN = "token:";
    @Resource
    RedisDao redisDao;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod method = (HandlerMethod) handler;
            ApiIdempotent annotation = method.getMethodAnnotation(ApiIdempotent.class);
            if (annotation != null) {
                String token = request.getHeader(API_IDEMPOTENT_TOKEN);
                if (!StringUtil.isNullOrEmpty(token)) {
                    String tokenPrefix = StringUtil.isNullOrEmpty(annotation.value()) ? DEFAULT_API_IDEMPOTENT_TOKEN : annotation.value();
                    String key = tokenPrefix + token;
                    if (redisDao.hasKey(key)) {
                        boolean isDel = redisDao.delete(key);
                        if (!isDel) {
                            throw new ApiIdempotentException(ResponseEnumCode.IDEMPOTENT_TOKEN_DELETE_ERROR);
                        }
                    } else {
                        throw new ApiIdempotentException(ResponseEnumCode.IDEMPOTENT_TOKEN_ERROR);
                    }
                } else {
                    throw new ApiIdempotentException(ResponseEnumCode.IDEMPOTENT_NOT_NULL_ERROR);
                }
            }
        }
        return true;
    }
}
